# -*- coding: utf-8 -*-

import re

class Montador:
    """ Classe que faz a montagem de programas MIPS """
    
    def __init__(self):
        
        self.regs = {
            '$0'  : '00000', '$1'  : '00001', '$2'  : '00010', '$3'  : '00011',
            '$4'  : '00100', '$5'  : '00101', '$6'  : '00110', '$7'  : '00111',
            '$8'  : '01000', '$9'  : '01001', '$10' : '01010', '$11' : '01011',
            '$12' : '01100', '$13' : '01101', '$14' : '01110', '$15' : '01111',
            '$16' : '10000', '$17' : '10001', '$18' : '10010', '$19' : '10011',
            '$20' : '10100', '$21' : '10101', '$22' : '10110', '$23' : '10111',
            '$24' : '11000', '$25' : '11001', '$26' : '11010', '$27' : '11011',
            '$28' : '11100', '$29' : '11101', '$30' : '11110', '$31' : '11111',
        }
        
        self.tabela_simbolo = {}
        self.prox_end = 0
        self.montado = False
        self.gerou_codigo = []
        self.linhas = {}
    
    def set_controle(self, controle):
        """ Faz a ligação com o controle do projeto """
        self.controle = controle
    
    
    def set_interface(self, interface):
        """ Faz a ligação com a iterface do projeto """
        self.interface = interface
    
        
    def set_arquitetura(self, arquitetura):
        """ Faz a ligação com a arquitetura """
        self.arquitetura = arquitetura
    
    def construir_ts(self, codigo):
        arquivo = open(codigo)
        linhas = arquivo.readlines()
        prox_end = 0
        
        for linha in linhas:
            d = re.search("^ *?(?P<rotulo>[a-zA-Z][\w_]*) *?:", linha)
            if d:
                self.tabela_simbolo[d.group('rotulo')] = prox_end
                print self.tabela_simbolo
            
            print "cts: %s" % linha
            
            d = re.search("^ *?(?P<diretiva>(\.data|\.space|\.text)) *?(?P<rabo>[^ ]*?)$", linha)
            if d:
                if d.group('diretiva') == ".space":
                    if d.group('rabo'):
                        try:
                            n = int(d.group('rabo'))
                        except:
                            self.controle.add_msg("Erro Montagem (%d): Espaço reservado deve ser um inteiro." % line)
                            # para a montagem
                            return False
                        #else:
                        if n % 4 != 0:
                            self.controle.add_msg("Erro Montagem (%d): Espaço reservado deve ser múltiplo de 4." % line)
                            # para a montagem
                            return False
                        print "aumentando prox_end em %d" % n
                        prox_end += n
                        continue
                    else:
                        self.controle.add_msg("Erro Montagem (%d): Espaço reservado deve ser informado." % line)
                        # para a montagem
                        return False            
            
            d = re.search ("syscall", linha)
            if(d):       
                prox_end+=4
                continue
            
            d = re.search ("ret", linha)
            if(d):       
                prox_end += 4
                continue    
            
            d = re.search("(^ *?(?P<rotulo>\w+?) *?:)? *?(?P<inst>\w+?) (?P<rabo>.*?)$", linha)
            print d
            if d:
                if d.group('inst'):
                    prox_end += 4
        arquivo.close()
    
    def assemble_code(self, codigo):
        arquivo = open(codigo)
        linhas = arquivo.readlines()
        self.prox_end = 0
        estado = "codigo"
        self.arquitetura.pc_ini = 0
        self.gerou_codigo = []
        self.linhas = {}
        self.construir_ts(codigo)
        
        for line, linha in enumerate(linhas):
            line += 1
            d = re.search("^ *?(?P<diretiva>(\.data|\.space|\.text)) *?(?P<rabo>[^ ]*?)$", linha)
            if d:
                print "encontrei diretiva %s" % d.group('diretiva')
                if d.group('diretiva') == ".data":
                    estado = "dados"
                    self.gerou_codigo.append(0)
                    continue
                if d.group('diretiva') == ".space" and estado == "dados":
                    if d.group('rabo'):
                        try:
                            n = int(d.group('rabo'))
                        except:
                            self.controle.add_msg("Erro Montagem (%d): Espaço reservado deve ser um inteiro." % line)
                            # para a montagem
                            return False
                        #else:
                        if n % 4 != 0:
                            self.controle.add_msg("Erro Montagem (%d): Espaço reservado deve ser múltiplo de 4." % line)
                            # para a montagem
                            return False
                        print "aumentando prox_end em %d" % n
                        self.prox_end += n
                        self.gerou_codigo.append(0)
                        continue
                    else:
                        self.controle.add_msg("Erro Montagem (%d): Espaço reservado deve ser informado." % line)
                        # para a montagem
                        return False
                if d.group('diretiva') == ".text":
                    self.arquitetura.set_pc_inicial(self.prox_end)
                    estado = "codigo"
                    self.gerou_codigo.append(0)
                    continue
            
            d = re.search("^ *?(?P<rotulo>[a-zA-Z][\w_]*) *?:", linha)
            if d:
                rotulada = True
            else:
                rotulada = False
            
            #consome linhas em branco
            d = re.search("^ *?$", linha)
            if(d):
                self.gerou_codigo.append(0)
                continue
            
            d = re.search ("syscall", linha)
            if(d):       
                codigo = eval("self.cod_syscall(None ,line)")
                if codigo:
                    print "%08X: %08X" % (self.prox_end, codigo)
                    self.arquitetura.set_mem_word(self.prox_end, codigo)
                    self.interface.add_mem(self.prox_end, codigo)
                    self.prox_end += 4
                    self.gerou_codigo.append(1)
                    continue
                else:
                    # para a montagem
                    return False                
            
            d = re.search ("ret", linha)
            if(d):       
                codigo = eval("self.cod_ret(None ,line)")
                if codigo:
                    print "%08X: %08X" % (self.prox_end, codigo)
                    self.arquitetura.set_mem_word(self.prox_end, codigo)
                    self.interface.add_mem(self.prox_end, codigo)
                    self.prox_end += 4
                    self.gerou_codigo.append(1)
                    continue
                else:
                    # para a montagem
                    return False                 
            
            print "prox_end %d " % self.prox_end
            
            if estado == "codigo":
                print linha
                d = re.search("(^ *?(?P<rotulo>\w+?) *?:)? *?(?P<inst>\w+?) (?P<rabo>.*?)$", linha)
                if d:
                    if d.group('inst'):
                        try:
                            codigo = eval("self.cod_%s(d.group('rabo') ,line)" % d.group('inst').lower())
                        except NameError:
                            self.controle.add_msg("Erro Montagem (%d): Instrução inválida" % line)
                            # para a montagem
                            return False
                        else:
                            if codigo:
                                print "%08X: %08X" % (self.prox_end, codigo)
                                self.arquitetura.set_mem_word(self.prox_end, codigo)
                                self.interface.add_mem(self.prox_end, codigo)
                                self.linhas[self.prox_end] = line
                                self.prox_end += 4
                                self.gerou_codigo.append(1)
                            else:
                                # para a montagem
                                return False

                else:
                    if rotulada:
                        self.gerou_codigo.append(0)
                        continue
                    else:
                        self.controle.add_msg("Erro Montagem (%d): Sintaxe inválida" % line)
                        # para a montagem
                        return False
        arquivo.close()
        return True
    
    def to_int(self, bin):
        """ Transforma uma string de binários em inteiro """
        n = list(bin)
        codigo_int, count = 0, 0
        while(n):
            valor = int(n.pop())
            codigo_int += valor * int(2**count)
            count += 1
        return codigo_int
    
    def to_bin(self, integer, tam):
        """ Transforma um inteiro em binário (string) """
        return "".join([str((integer >> y) & 1) for y in range(tam -1, -1, -1)])
    
    
    def cod_add(self, resto, linha):
        d = re.search('(?P<a>\$\d{1,2}) *?, *?(?P<b>\$\d{1,2}) *?, *?(?P<c>\$\d{1,2})', resto)
        print "op_s = %s, op_t = %s, op_d = %s" % (self.regs[d.group('b')], self.regs[d.group('c')], self.regs[d.group('a')])
        if d:
            if d.group('a').lower() in self.regs and \
                    d.group('b').lower() in self.regs and \
                    d.group('c').lower() in self.regs:
                codigo_bin = "000000%s%s%s00000100000" % (self.regs[d.group('b')],
                                                        self.regs[d.group('c')],
                                                        self.regs[d.group('a')])
                print codigo_bin
                return self.to_int(codigo_bin)
            else:
                self.controle.add_msg("Erro Montagem (%d): Os operandos da instrução 'add' devem ser todos registradores" % linha)
                return None
        else:
            self.controle.add_msg("Erro Montagem (%d): A instrução 'add' deve ter 3 operandos" % linha)
            return None
    
    def cod_addi(self, resto, linha):
        d = re.search('(?P<a>\$\d{1,2}) *?, *?(?P<b>\$\d{1,2}) *?, *?((?P<c>(\d{1,5}))|(?P<r>[a-zA-Z][\w_]*?))$', resto)
        if d:
            
            if(d.group('c')):
                imm = int(d.group('c'))
            elif (d.group('r')):
                try:
                    imm = int(self.tabela_simbolo[d.group('r')])
                except KeyError:
                    self.controle.add_msg("Erro Montagem (%d): Símbolo %s indefinido!" % (linha, d.group('r')))
                    return None
                
            if d.group('a').lower() in self.regs and \
                    d.group('b').lower() in self.regs:
                codigo_bin = "001000%s%s%s" % (self.regs[d.group('b').lower()],
                                                        self.regs[d.group('a').lower()],
                                                        self.to_bin(imm, 16)
                                                )
                return self.to_int(codigo_bin)
            else:
                self.controle.add_msg("Erro Montagem (%d): Os operandos da instrução 'addi' são dois registradores seguidos por um valor imediato de 16-bits" % linha)
                return None
        else:
            self.controle.add_msg("Erro Montagem (%d): Formato da instrução 'addi': $d, $s, imd onde imd é um imediato ou rótulo" % linha)
            return None        
    
    def cod_addiu(self, resto, linha):
        d = re.search('(?P<a>\$\d{1,2}) *?, *?(?P<b>\$\d{1,2}) *?, *?((?P<c>(\d{1,5}))|(?P<r>[a-zA-Z][\w_]*?))$', resto)
        if d:
            
            if(d.group('c')):
                imm = int(d.group('c'))
            elif (d.group('r')):
                try:
                    imm = int(self.tabela_simbolo[d.group('r')])
                except KeyError:
                    self.controle.add_msg("Erro Montagem (%d): Símbolo %s indefinido!" % (linha, d.group('r')))
                    return None
                
            if d.group('a').lower() in self.regs and \
                    d.group('b').lower() in self.regs:
                codigo_bin = "001001%s%s%s" % (self.regs[d.group('b').lower()],
                                                        self.regs[d.group('a').lower()],
                                                        self.to_bin(imm, 16)
                                                        )
                return self.to_int(codigo_bin)
            else:
                self.controle.add_msg("Erro Montagem (%d): Os operandos da instrução 'addiu' são dois registradores seguidos por um valor imediato de 16-bits" % linha)
                return None
        else:
            self.controle.add_msg("Erro Montagem (%d): Formato da instrução 'addiu': $d, $s, imd onde imd é um imediato ou rótulo" % linha)
            return None      
    
    def cod_addu(self, resto, linha):
        d = re.search('(?P<a>\$\d{1,2}) *?, *?(?P<b>\$\d{1,2}) *?, *?(?P<c>\$\d{1,2})', resto)
        if d:
            if d.group('a').lower() in self.regs and \
                    d.group('b').lower() in self.regs and \
                    d.group('c').lower() in self.regs:
                codigo_bin = "000000%s%s%s00000100001" % (self.regs[d.group('b').lower()],
                                                        self.regs[d.group('c').lower()],
                                                        self.regs[d.group('a').lower()])
                return self.to_int(codigo_bin)
            else:
                self.controle.add_msg("Erro Montagem (%d): Os operandos da instrução 'addu' devem ser todos registradores" % linha)
                return None
        else:
            self.controle.add_msg("Erro Montagem (%d): A instrução 'addu' deve ter 3 operandos" % linha)
            return None        
    
    def cod_and(self, resto, linha):
        d = re.search('(?P<a>\$\d{1,2}) *?, *?(?P<b>\$\d{1,2}) *?, *?(?P<c>\$\d{1,2})', resto)
        if d:
            if d.group('a').lower() in self.regs and \
                    d.group('b').lower() in self.regs and \
                    d.group('c').lower() in self.regs:
                codigo_bin = "000000%s%s%s00000100100" % (self.regs[d.group('b').lower()],
                                                        self.regs[d.group('c').lower()],
                                                        self.regs[d.group('a').lower()])
                return self.to_int(codigo_bin)
            else:
                self.controle.add_msg("Erro Montagem (%d): Os operandos da instrução 'and' devem ser todos registradores" % linha)
                return None
        else:
            self.controle.add_msg("Erro Montagem (%d): A instrução 'and' deve ter 3 operandos" % linha)
            return None            
    
    def cod_andi(self, resto, linha):
        d = re.search('(?P<a>\$\d{1,2}) *?, *?(?P<b>\$\d{1,2}) *?, *?((?P<c>(\d{1,5}))|(?P<r>[a-zA-Z][\w_]*?))$', resto)
        if d:
            
            if(d.group('c')):
                imm = int(d.group('c'))
            elif (d.group('r')):
                try:
                    imm = int(self.tabela_simbolo[d.group('r')])
                except KeyError:
                    self.controle.add_msg("Erro Montagem (%d): Símbolo %s indefinido!" % (linha, d.group('r')))
                    return None
                
            if d.group('a').lower() in self.regs and \
                    d.group('b').lower() in self.regs:
                codigo_bin = "001100%s%s%s" % (self.regs[d.group('b').lower()],
                                                        self.regs[d.group('a').lower()],
                                                        self.to_bin(imm, 16)
                                                        )
                return self.to_int(codigo_bin)
            else:
                self.controle.add_msg("Erro Montagem (%d): Os operandos da instrução 'andi' são dois registradores seguidos por um valor imediato de 16-bits" % linha)
                return None
        else:
            self.controle.add_msg("Erro Montagem (%d): Formato da instrução 'andi': $d, $s, imd onde imd é um imediato ou rótulo" % linha)
            return None    
    
    def cod_beq(self, resto, linha):
        d = re.search('(?P<a>\$\d{1,2}) *?, *?(?P<b>\$\d{1,2}) *?, *?((?P<c>(\d{1,5}))|(?P<r>[a-zA-Z][\w_]*?))$', resto)
        if d:
            
            if(d.group('c')):
                imm = int(d.group('c'))
            elif (d.group('r')):
                try:
                    imm = int(self.tabela_simbolo[d.group('r')])
                except KeyError:
                    self.controle.add_msg("Erro Montagem (%d): Símbolo %s indefinido!" % (linha, d.group('r')))
                    return None
            
            print "imm - self.prox_end = %d" % (imm - self.prox_end)
            desl = (imm - self.prox_end) >> 2;
            print "desl = %d" % desl
            if d.group('a').lower() in self.regs and \
                    d.group('b').lower() in self.regs:
                codigo_bin = "000100%s%s%s" % (self.regs[d.group('a').lower()],
                                                        self.regs[d.group('b').lower()],
                                                        self.to_bin(desl, 16)
                                                        )
                return self.to_int(codigo_bin)
            else:
                self.controle.add_msg("Erro Montagem (%d): Os operandos da instrução 'beq' são dois registradores seguidos por um salto relativo de 16-bits (em words)" % linha)
                return None
        else:
            self.controle.add_msg("Erro Montagem (%d): Formato da instrução 'beq': $d, $s, desl onde desl é um deslocamento relativo em rótulo ou imediato" % linha)
            return None   
    
    def cod_bgez(self, resto, linha):
        d = re.search('(?P<a>\$\d{1,2}) *?, *?((?P<c>(\d{1,5}))|(?P<r>[a-zA-Z][\w_]*?))$', resto)
        if d:
            
            if(d.group('c')):
                imm = int(d.group('c'))
            elif (d.group('r')):
                try:
                    imm = int(self.tabela_simbolo[d.group('r')])
                except KeyError:
                    self.controle.add_msg("Erro Montagem (%d): Símbolo %s indefinido!" % (linha, d.group('r')))
                    return None
            
            desl = (imm - self.prox_end) >> 2
            
            if d.group('a').lower() in self.regs:
                codigo_bin = "000001%s00001%s" % (self.regs[d.group('a').lower()],
                                                        self.to_bin(desl, 16)
                                                        )
                return self.to_int(codigo_bin)
            else:
                self.controle.add_msg("Erro Montagem (%d): Os operandos da instrução 'bgez' são dois registradores seguidos por um salto relativo de 16-bits (em words)" % linha)
                return None
        else:
            self.controle.add_msg("Erro Montagem (%d): Formato da instrução 'beq': $d, desl onde desl é um deslocamento relativo em rótulo ou imediato" % linha)
            return None  
    
    def cod_bgezal(self, resto, linha):
        d = re.search('(?P<a>\$\d{1,2}) *?, *?((?P<c>(\d{1,5}))|(?P<r>[a-zA-Z][\w_]*?))$', resto)
        if d:
            
            if(d.group('c')):
                imm = int(d.group('c'))
            elif (d.group('r')):
                try:
                    imm = int(self.tabela_simbolo[d.group('r')])
                except KeyError:
                    self.controle.add_msg("Erro Montagem (%d): Símbolo %s indefinido!" % (linha, d.group('r')))
                    return None
            
            desl = (imm - self.prox_end) >> 2
            
            if d.group('a').lower() in self.regs:
                codigo_bin = "000001%s10001%s" % (self.regs[d.group('a').lower()],
                                                        self.to_bin(desl, 16)
                                                        )
                return self.to_int(codigo_bin)
            else:
                self.controle.add_msg("Erro Montagem (%d): Os operandos da instrução 'bgezal' são dois registradores seguidos por um salto relativo de 16-bits (em words)" % linha)
                return None
        else:
            self.controle.add_msg("Erro Montagem (%d): Formato da instrução 'bgezal': $d, desl onde desl é um deslocamento relativo em rótulo ou imediato" % linha)
            return None  
    
    def cod_bgtz(self, resto, linha):
        d = re.search('(?P<a>\$\d{1,2}) *?, *?((?P<c>(\d{1,5}))|(?P<r>[a-zA-Z][\w_]*?))$', resto)
        if d:
            
            if(d.group('c')):
                imm = int(d.group('c'))
            elif (d.group('r')):
                try:
                    imm = int(self.tabela_simbolo[d.group('r')])
                except KeyError:
                    self.controle.add_msg("Erro Montagem (%d): Símbolo %s indefinido!" % (linha, d.group('r')))
                    return None
            
            desl = (imm - self.prox_end) >> 2                
                
            if d.group('a').lower() in self.regs:
                codigo_bin = "000111%s00000%s" % (self.regs[d.group('a').lower()],
                                                        self.to_bin(desl, 16)
                                                )
                return self.to_int(codigo_bin)
            else:
                self.controle.add_msg("Erro Montagem (%d): Os operandos da instrução 'bgtz' são dois registradores seguidos por um salto relativo de 16-bits (em words)" % linha)
                return None
        else:
            self.controle.add_msg("Erro Montagem (%d): Formato da instrução 'bgtz': $d, desl onde desl é um deslocamento relativo em rótulo ou imediato" % linha)
            return None  
    
    def cod_blez(self, resto, linha):
        d = re.search('(?P<a>\$\d{1,2}) *?, *?((?P<c>(\d{1,5}))|(?P<r>[a-zA-Z][\w_]*?))$', resto)
        if d:
            
            if(d.group('c')):
                imm = int(d.group('c'))
            elif (d.group('r')):
                try:
                    imm = int(self.tabela_simbolo[d.group('r')])
                except KeyError:
                    self.controle.add_msg("Erro Montagem (%d): Símbolo %s indefinido!" % (linha, d.group('r')))
                    return None
            
            desl = (imm - self.prox_end) >> 2
            
            if d.group('a').lower() in self.regs:
                codigo_bin = "000110%s00000%s" % (self.regs[d.group('a').lower()],
                                                        self.to_bin(desl, 16)
                                                        )
                return self.to_int(codigo_bin)
            else:
                self.controle.add_msg("Erro Montagem (%d): Os operandos da instrução 'blez' são dois registradores seguidos por um salto relativo de 16-bits (em words)" % linha)
                return None
        else:
            self.controle.add_msg("Erro Montagem (%d): Formato da instrução 'blez': $d, desl onde desl é um deslocamento relativo em rótulo ou imediato" % linha)
            return None  
    
    def cod_bltz(self, resto, linha):
        d = re.search('(?P<a>\$\d{1,2}) *?, *?((?P<c>(\d{1,5}))|(?P<r>[a-zA-Z][\w_]*?))$', resto)
        if d:
            
            if(d.group('c')):
                imm = int(d.group('c'))
            elif (d.group('r')):
                try:
                    imm = int(self.tabela_simbolo[d.group('r')])
                except KeyError:
                    self.controle.add_msg("Erro Montagem (%d): Símbolo %s indefinido!" % (linha, d.group('r')))
                    return None
            
            desl = (imm - self.prox_end) >> 2
            
            if d.group('a').lower() in self.regs:
                codigo_bin = "000001%s00000%s" % (self.regs[d.group('a').lower()],
                                                        self.to_bin(desl, 16)
                                                        )
                return self.to_int(codigo_bin)
            else:
                self.controle.add_msg("Erro Montagem (%d): Os operandos da instrução 'bltz' são dois registradores seguidos por um salto relativo de 16-bits (em words)" % linha)
                return None
        else:
            self.controle.add_msg("Erro Montagem (%d): Formato da instrução 'bltz': $d, desl onde desl é um deslocamento relativo em rótulo ou imediato" % linha)
            return None  
    
    def cod_bltzal(self, resto, linha):
        d = re.search('(?P<a>\$\d{1,2}) *?, *?((?P<c>(\d{1,5}))|(?P<r>[a-zA-Z][\w_]*?))$', resto)
        if d:
            
            if(d.group('c')):
                imm = int(d.group('c'))
            elif (d.group('r')):
                try:
                    imm = int(self.tabela_simbolo[d.group('r')])
                except KeyError:
                    self.controle.add_msg("Erro Montagem (%d): Símbolo %s indefinido!" % (linha, d.group('r')))
                    return None
            
            desl = (imm - self.prox_end) >> 2
            
            if d.group('a').lower() in self.regs:
                codigo_bin = "000001%s10000%s" % (self.regs[d.group('a').lower()],
                                                        self.to_bin(desl, 16)
                                                        )
                return self.to_int(codigo_bin)
            else:
                self.controle.add_msg("Erro Montagem (%d): Os operandos da instrução 'bltzal' são um registrador seguido por um salto relativo de 16-bits (em words)" % linha)
                return None
        else:
            self.controle.add_msg("Erro Montagem (%d): Formato da instrução 'bltzal': $d, desl onde desl é um deslocamento relativo em rótulo ou imediato" % linha)
            return None  
    
    def cod_bne(self, resto, linha):
        d = re.search('(?P<a>\$\d{1,2}) *?, *?(?P<b>\$\d{1,2}) *?, *?((?P<c>(\d{1,5}))|(?P<r>[a-zA-Z][\w_]*?))$', resto)
        if d:
            
            if(d.group('c')):
                imm = int(d.group('c'))
            elif (d.group('r')):
                try:
                    imm = int(self.tabela_simbolo[d.group('r')])
                except KeyError:
                    self.controle.add_msg("Erro Montagem (%d): Símbolo %s indefinido!" % (linha, d.group('r')))
                    return None
            
            desl = (imm - self.prox_end) >> 2;
                
            if d.group('a').lower() in self.regs and \
                    d.group('b').lower() in self.regs:
                
                codigo_bin = "000101%s%s%s" % (self.regs[d.group('a').lower()],
                                                        self.regs[d.group('b').lower()],
                                                        self.to_bin(desl, 16)
                                                        )
                return self.to_int(codigo_bin)
            else:
                self.controle.add_msg("Erro Montagem (%d): Os operandos da instrução 'bne' são dois registradores seguidos por um salto relativo de 16-bits (em words)" % linha)
                return None
        else:
            self.controle.add_msg("Erro Montagem (%d): Formato da instrução 'bne': $d, $s, desl onde desl é um deslocamento relativo em rótulo ou imediato" % linha)
            return None   
    
    def cod_div(self, resto, linha):
        d = re.search('(?P<a>\$\d{1,2}) *?, *?(?P<c>\$\d{1,2})', resto)
        if d:
            if d.group('a').lower() in self.regs and \
                    d.group('c').lower() in self.regs:
                codigo_bin = "000000%s%s0000000000011010" % (self.regs[d.group('a').lower()],
                                                        self.regs[d.group('c').lower()])
                return self.to_int(codigo_bin)
            else:
                self.controle.add_msg("Erro Montagem (%d): Os operandos da instrução 'div' devem ser todos registradores" % linha)
                return None
        else:
            self.controle.add_msg("Erro Montagem (%d): A instrução 'div' deve ter 2 operandos" % linha)
            return None 
    
    def cod_divu(self, resto, linha):
        d = re.search('(?P<a>\$\d{1,2}) *?, *?(?P<c>\$\d{1,2})', resto)
        if d:
            if d.group('a').lower() in self.regs and \
                    d.group('c').lower() in self.regs:
                codigo_bin = "000000%s%s0000000000011011" % (self.regs[d.group('a').lower()],
                                                        self.regs[d.group('c').lower()])
                return self.to_int(codigo_bin)
            else:
                self.controle.add_msg("Erro Montagem (%d): Os operandos da instrução 'divu' devem ser todos registradores" % linha)
                return None
        else:
            self.controle.add_msg("Erro Montagem (%d): A instrução 'divu' deve ter 2 operandos" % linha)
            return None 
    
    def cod_j(self, resto, linha):
        d = re.search("^ *?(?P<r>[a-zA-Z][\w_]*?)$", resto)
        if d:
            try:
                destino = self.tabela_simbolo[d.group('r')]
                print destino
            except KeyError:
                self.controle.add_msg("Erro Montagem (%d): Símbolo %s indefinido!" % (linha, d.group('r')))    
            else:
                codigo_bin = "000010%s" % self.to_bin(destino >> 2, 26)
                return self.to_int(codigo_bin)
        else:
            self.controle.add_msg("Erro Montagem (%d): A instrução 'j' deve ter 1 operando" % linha)
            return None
            
    
    def cod_jal(self, resto, linha):
        d = re.search("^ *?(?P<r>[a-zA-Z][\w_]*?)$", resto)
        if d:
            try:
                destino = self.tabela_simbolo[d.group('r')]
                print destino
            except KeyError:
                self.controle.add_msg("Erro Montagem (%d): Símbolo %s indefinido!" % (linha, d.group('r')))    
            else:
                codigo_bin = "000011%s" % self.to_bin(destino, 26)
                return self.to_int(codigo_bin)
        else:
            self.controle.add_msg("Erro Montagem (%d): A instrução 'jal' deve ter 1 operando" % linha)
            return None
    
    def cod_jr(self, resto, linha):
        d = re.search('(?P<a>\$\d{1,2}) *?', resto)
        if d:
            if d.group('a').lower() in self.regs:
                codigo_bin = "000000%s000000000000000001000" % self.regs[d.group('a').lower()]
                return self.to_int(codigo_bin)
            else:
                self.controle.add_msg("Erro Montagem (%d): O operando da instrução 'jr' deve ser um registrador" % linha)
                return None
        else:
            self.controle.add_msg("Erro Montagem (%d): A instrução 'jr' deve ter 1 operando" % linha)
            return None
    
    def cod_lb(self, resto, linha):
        d = re.search("(?P<a>\$\d{1,2}) *?, *?((?P<o>(\d{1,5}))|(?P<r>[a-zA-Z][\w_]*?)) *?\( *?(?P<c>\$\d{1,2}) *?\) *?", resto)
        if d:
            
            if(d.group('o')):
                imm = int(d.group('o'))
            elif (d.group('r')):
                try:
                    imm = int(self.tabela_simbolo[d.group('r')])
                except KeyError:
                    self.controle.add_msg("Erro Montagem (%d): Símbolo %s indefinido!" % (linha, d.group('r')))
                    return None                
            
            if d.group('a').lower() in self.regs and \
                    d.group('c').lower() in self.regs:
                codigo_bin = "100000%s%s%s" % (self.regs[d.group('c').lower()],
                                                    self.regs[d.group('a')],
                                                    self.to_bin(imm, 16)
                                              )
                return self.to_int(codigo_bin)
            else:
                self.controle.add_msg("Erro Montagem (%d): O operando da instrução 'lb' deve estar no formato lb $r1, offset($r2)" % linha)
                return None
        else:
            self.controle.add_msg("Erro Montagem (%d): Formato da instrução 'lb': lb $r1, offset($r2) onde offset pode ser um imediato ou um símbolo")
            return None
    
    def cod_lui(self, resto, linha):
        d = re.search('(?P<a>\$\d{1,2}) *?, *?((?P<c>(\d{1,5}))|(?P<r>[a-zA-Z][\w_]*?))$', resto)
        if d:
            
            if(d.group('c')):
                imm = int(d.group('c'))
            elif (d.group('r')):
                try:
                    imm = int(self.tabela_simbolo[d.group('r')])
                except KeyError:
                    self.controle.add_msg("Erro Montagem (%d): Símbolo %s indefinido!" % (linha, d.group('r')))
                    return None
                
            if d.group('a').lower() in self.regs:
                
                codigo_bin = "00111100000%s%s" % (self.regs[d.group('a').lower()],
                                                        self.to_bin(imm, 16)
                                                        )
                return self.to_int(codigo_bin)
            else:
                self.controle.add_msg("Erro Montagem (%d): Os operandos da instrução 'lui' são dois registradores seguidos por um imediato de 16-bits" % linha)
                return None
        else:
            self.controle.add_msg("Erro Montagem (%d): Formato da instrução 'lui': $d, imd onde imd é um imediato ou rótulo" % linha)
            return None  
    
    def cod_lw(self, resto, linha):
        d = re.search("(?P<a>\$\d{1,2}) *?, *?((?P<o>(\d{1,5}))|(?P<r>[a-zA-Z][\w_]*?)) *?\( *?(?P<c>\$\d{1,2}) *?\) *?", resto)
        if d:
            
            if(d.group('o')):
                imm = int(d.group('o'))
            elif (d.group('r')):
                try:
                    imm = int(self.tabela_simbolo[d.group('r')])
                except KeyError:
                    self.controle.add_msg("Erro Montagem (%d): Símbolo %s indefinido!" % (linha, d.group('r')))
                    return None            
            
            if d.group('a').lower() in self.regs and \
                    d.group('c').lower() in self.regs:
                codigo_bin = "100011%s%s%s" % (self.regs[d.group('c').lower()],
                                                    self.regs[d.group('a')],
                                                    self.to_bin(imm, 16)
                                              )
                return self.to_int(codigo_bin)
            else:
                self.controle.add_msg("Erro Montagem (%d): O operando da instrução 'lw' deve estar no formato lw $r1, offset($r2)" % linha)
                return None
        else:
            self.controle.add_msg("Erro Montagem (%d): Formato da instrução 'lw': lw $r1, offset($r2) onde offset pode ser um imediato ou um símbolo")
            return None
    
    def cod_mfhi(self, resto, linha):
        d = re.search('(?P<a>\$\d{1,2}) *?', resto)
        if d:
            if d.group('a').lower() in self.regs:
                codigo_bin = "0000000000000000%s00000010000" % (self.regs[d.group('a').lower()])
                return self.to_int(codigo_bin)
            else:
                self.controle.add_msg("Erro Montagem (%d): O operando da instrução 'mfhi' deve ser um único registrador" % linha)
                return None
        else:
            self.controle.add_msg("Erro Montagem (%d): A instrução 'mfhi' deve ter 1 operando" % linha)
            return None
        
    def cod_push(self, resto, linha):
        d = re.search('(?P<a>\$\d{1,2}) *?', resto)
        if d:
            if d.group('a').lower() in self.regs:
                codigo_bin = "0000000000000000%s00000010011" % (self.regs[d.group('a').lower()])
                return self.to_int(codigo_bin)
            else:
                self.controle.add_msg("Erro Montagem (%d): O operando da instrução 'push' deve ser um único registrador" % linha)
                return None
        else:
            self.controle.add_msg("Erro Montagem (%d): A instrução 'push' deve ter 1 operando" % linha)
            return None             
    
    def cod_pop(self, resto, linha):
        d = re.search('(?P<a>\$\d{1,2}) *?', resto)
        if d:
            if d.group('a').lower() in self.regs:
                codigo_bin = "0000000000000000%s00000010100" % (self.regs[d.group('a').lower()])
                return self.to_int(codigo_bin)
            else:
                self.controle.add_msg("Erro Montagem (%d): O operando da instrução 'pop' deve ser um único registrador" % linha)
                return None
        else:
            self.controle.add_msg("Erro Montagem (%d): A instrução 'pop' deve ter 1 operando" % linha)
            return None     
    
    def cod_call(self, resto, linha):
        d = re.search("^ *?(?P<r>[a-zA-Z][\w_]*?)$", resto)
        if d:
            try:
                destino = self.tabela_simbolo[d.group('r')]
                print destino
            except KeyError:
                self.controle.add_msg("Erro Montagem (%d): Símbolo %s indefinido!" % (linha, d.group('r')))    
            else:
                codigo_bin = "111110%s" % self.to_bin(destino >> 2, 26)
                return self.to_int(codigo_bin)
        else:
            self.controle.add_msg("Erro Montagem (%d): Formato da instrução call: call label" % linha)
            return None    
    
    def cod_ret(self, resto, linha):
        codigo_bin = "11111100000000000000000000000000"
        return self.to_int(codigo_bin)
    
    def cod_mflo(self, resto, linha):
        d = re.search('(?P<a>\$\d{1,2}) *?', resto)
        if d:
            if d.group('a').lower() in self.regs:
                codigo_bin = "0000000000000000%s00000010010" % (self.regs[d.group('a').lower()])
                return self.to_int(codigo_bin)
            else:
                self.controle.add_msg("Erro Montagem (%d): O operando da instrução 'mflo' deve ser um único registrador" % linha)
                return None
        else:
            self.controle.add_msg("Erro Montagem (%d): A instrução 'mflo' deve ter 1 operando" % linha)
            return None
    
    def cod_mult(self, resto, linha):
        d = re.search('(?P<a>\$\d{1,2}) *?, *?(?P<c>\$\d{1,2})', resto)
        if d:
            if d.group('a').lower() in self.regs and \
                    d.group('c').lower() in self.regs:
                codigo_bin = "000000%s%s0000000000011000" % (self.regs[d.group('a').lower()],
                                                        self.regs[d.group('c').lower()])
                return self.to_int(codigo_bin)
            else:
                self.controle.add_msg("Erro Montagem (%d): Os operandos da instrução 'mult' devem ser todos registradores" % linha)
                return None
        else:
            self.controle.add_msg("Erro Montagem (%d): A instrução 'mult' deve ter 2 operandos" % linha)
            return None         
    
    def cod_multu(self, resto, linha):
        d = re.search('(?P<a>\$\d{1,2}) *?, *?(?P<c>\$\d{1,2})', resto)
        if d:
            if d.group('a').lower() in self.regs and \
                    d.group('c').lower() in self.regs:
                codigo_bin = "000000%s%s0000000000011001" % (self.regs[d.group('a').lower()],
                                                        self.regs[d.group('c').lower()])
                return self.to_int(codigo_bin)
            else:
                self.controle.add_msg("Erro Montagem (%d): Os operandos da instrução 'multu' devem ser todos registradores" % linha)
                return None
        else:
            self.controle.add_msg("Erro Montagem (%d): A instrução 'multu' deve ter 2 operandos" % linha)
            return None         
    
    def cod_noop(self, resto, linha):
        codigo_bin = "00000000000000000000000000000000"
        return self.to_int(codigo_bin)
    
    def cod_or(self, resto, linha):
        d = re.search('(?P<a>\$\d{1,2}) *?, *?(?P<b>\$\d{1,2}) *?, *?(?P<c>\$\d{1,2})', resto)
        if d:
            if d.group('a').lower() in self.regs and \
                    d.group('b').lower() in self.regs and \
                    d.group('c').lower() in self.regs:
                codigo_bin = "000000%s%s%s00000100101" % (self.regs[d.group('b').lower()],
                                                        self.regs[d.group('c').lower()],
                                                        self.regs[d.group('a').lower()])
                return self.to_int(codigo_bin)
            else:
                self.controle.add_msg("Erro Montagem (%d): Os operandos da instrução 'or' devem ser todos registradores" % linha)
                return None
        else:
            self.controle.add_msg("Erro Montagem (%d): A instrução 'or' deve ter 3 operandos" % linha)
            return None           
    
    def cod_ori(self, resto, linha):
        d = re.search('(?P<a>\$\d{1,2}) *?, *?(?P<b>\$\d{1,2}) *?, *?((?P<c>(\d{1,5}))|(?P<r>[a-zA-Z][\w_]*?))$', resto)
        if d:
            
            if(d.group('c')):
                imm = int(d.group('c'))
            elif (d.group('r')):
                try:
                    imm = int(self.tabela_simbolo[d.group('r')])
                except KeyError:
                    self.controle.add_msg("Erro Montagem (%d): Símbolo %s indefinido!" % (linha, d.group('r')))
                    return None
                
            if d.group('a').lower() in self.regs and \
                    d.group('b').lower() in self.regs:
                codigo_bin = "001101%s%s%s" % (self.regs[d.group('b').lower()],
                                                        self.regs[d.group('a').lower()],
                                                        self.to_bin(imm, 16)
                                                        )
                return self.to_int(codigo_bin)
            else:
                self.controle.add_msg("Erro Montagem (%d): Os operandos da instrução 'ori' são dois registradores seguidos por um valor imediato de 16-bits" % linha)
                return None
        else:
            self.controle.add_msg("Erro Montagem (%d): Formato da instrução 'ori': $d, $s, imd onde imd é um imediato ou rótulo" % linha)
            return None
    
    def cod_sb(self, resto, linha):
        d = re.search("(?P<a>\$\d{1,2}) *?, *?((?P<o>(\d{1,5}))|(?P<r>[a-zA-Z][\w_]*?)) *?\( *?(?P<c>\$\d{1,2}) *?\) *?", resto)
        if d:
            
            if(d.group('o')):
                imm = int(d.group('o'))
            elif (d.group('r')):
                try:
                    imm = int(self.tabela_simbolo[d.group('r')])
                except KeyError:
                    self.controle.add_msg("Erro Montagem (%d): Símbolo %s indefinido!" % (linha, d.group('r')))
                    return None                     
            
            if d.group('a').lower() in self.regs and \
                    d.group('c').lower() in self.regs:
                codigo_bin = "101000%s%s%s" % (self.regs[d.group('c').lower()],
                                                    self.regs[d.group('a')],
                                                    self.to_bin(imm, 16)
                                              )
                return self.to_int(codigo_bin)
            else:
                self.controle.add_msg("Erro Montagem (%d): O operando da instrução 'sb' deve estar no formato sb $r1, offset($r2)" % linha)
                return None
        else:
            self.controle.add_msg("Erro Montagem (%d): Formato da instrução 'sb': sb $r1, offset($r2) onde offset pode ser um imediato ou um símbolo")
            return None
    
    def cod_sll(self, resto, linha):
        d = re.search('(?P<a>\$\d{1,2}) *?, *?(?P<b>\$\d{1,2}) *?, *?(?P<c>\d{1,2})', resto)
        if d:
            if d.group('a').lower() in self.regs and \
                    d.group('b').lower() in self.regs and \
                    d.group('c'):
                codigo_bin = "00000000000%s%s%s000000" % (self.regs[d.group('b').lower()],
                                                        self.regs[d.group('a').lower()],
                                                        self.to_bin(int(d.group('c')), 5)
                                                        )
                return self.to_int(codigo_bin)
            else:
                self.controle.add_msg("Erro Montagem (%d): Os operandos da instrução 'sll' são dois registradores seguidos por um deslocamento de 5-bits (0-31)" % linha)
                return None
        else:
            self.controle.add_msg("Erro Montagem (%d): A instrução 'sll' deve ter 3 operandos" % linha)
            return None  
    
    def cod_sllv(self, resto, linha):       
        d = re.search('(?P<a>\$\d{1,2}) *?, *?(?P<b>\$\d{1,2}) *?, *?(?P<c>\$\d{1,2})', resto)
        if d:
            if d.group('a').lower() in self.regs and \
                    d.group('b').lower() in self.regs and \
                    d.group('c').lower() in self.regs:
                codigo_bin = "000000%s%s%s00000000100" % (self.regs[d.group('c').lower()],
                                                        self.regs[d.group('b').lower()],
                                                        self.regs[d.group('a').lower()])
                print codigo_bin
                return self.to_int(codigo_bin)
            else:
                self.controle.add_msg("Erro Montagem (%d): Os operandos da instrução 'sllv' devem ser todos registradores" % linha)
                return None
        else:
            self.controle.add_msg("Erro Montagem (%d): A instrução 'sllv' deve ter 3 operandos" % linha)
            return None           
    
    def cod_slt(self, resto, linha):
        d = re.search('(?P<a>\$\d{1,2}) *?, *?(?P<b>\$\d{1,2}) *?, *?(?P<c>\$\d{1,2})', resto)
        if d:
            if d.group('a').lower() in self.regs and \
                    d.group('b').lower() in self.regs and \
                    d.group('c').lower() in self.regs:
                codigo_bin = "000000%s%s%s00000101010" % (self.regs[d.group('b').lower()],
                                                        self.regs[d.group('c').lower()],
                                                        self.regs[d.group('a').lower()])
                return self.to_int(codigo_bin)
            else:
                self.controle.add_msg("Erro Montagem (%d): Os operandos da instrução 'slt' devem ser todos registradores" % linha)
                return None
        else:
            self.controle.add_msg("Erro Montagem (%d): A instrução 'slt' deve ter 3 operandos" % linha)
            return None             
    
    def cod_slti(self, resto, linha):
        d = re.search('(?P<a>\$\d{1,2}) *?, *?(?P<b>\$\d{1,2}) *?, *?((?P<c>(\d{1,5}))|(?P<r>[a-zA-Z][\w_]*?))$', resto)
        if d:
            if(d.group('c')):
                imm = int(d.group('c'))
            elif (d.group('r')):
                try:
                    imm = int(self.tabela_simbolo[d.group('r')])
                except KeyError:
                    self.controle.add_msg("Erro Montagem (%d): Símbolo %s indefinido!" % (linha, d.group('r')))
                    return None
                
            if d.group('a').lower() in self.regs and \
                    d.group('b').lower() in self.regs:
                codigo_bin = "001010%s%s%s" % (self.regs[d.group('b').lower()],
                                                        self.regs[d.group('a').lower()],
                                                        self.to_bin(imm, 16)
                                                        )
                return self.to_int(codigo_bin)
            else:
                self.controle.add_msg("Erro Montagem (%d): Os operandos da instrução 'slti' são dois registradores seguidos por um valor imediato de 16-bits" % linha)
                return None
        else:
            self.controle.add_msg("Erro Montagem (%d): Formato da instrução 'slti': $d, $s, imd onde imd é um imediato ou rótulo" % linha)
            return None
    
    def cod_sltiu(self, resto, linha):
        d = re.search('(?P<a>\$\d{1,2}) *?, *?(?P<b>\$\d{1,2}) *?, *?((?P<c>(\d{1,5}))|(?P<r>[a-zA-Z][\w_]*?))$', resto)
        if d:
            if(d.group('c')):
                imm = int(d.group('c'))
            elif (d.group('r')):
                try:
                    imm = int(self.tabela_simbolo[d.group('r')])
                except KeyError:
                    self.controle.add_msg("Erro Montagem (%d): Símbolo %s indefinido!" % (linha, d.group('r')))
                    return None
                
            if d.group('a').lower() in self.regs and \
                    d.group('b').lower() in self.regs:
                codigo_bin = "001011%s%s%s" % (self.regs[d.group('b').lower()],
                                                        self.regs[d.group('a').lower()],
                                                        self.to_bin(imm, 16)
                                                        )
                return self.to_int(codigo_bin)
            else:
                self.controle.add_msg("Erro Montagem (%d): Os operandos da instrução 'sltiu' são dois registradores seguidos por um valor imediato de 16-bits" % linha)
                return None
        else:
            self.controle.add_msg("Erro Montagem (%d): Formato da instrução 'sltiu': $d, $s, imd onde imd é um imediato ou rótulo" % linha)
            return None
    
    def cod_sltu(self, resto, linha):
        d = re.search('(?P<a>\$\d{1,2}) *?, *?(?P<b>\$\d{1,2}) *?, *?(?P<c>\$\d{1,2})', resto)
        if d:
            if d.group('a').lower() in self.regs and \
                    d.group('b').lower() in self.regs and \
                    d.group('c').lower() in self.regs:
                codigo_bin = "000000%s%s%s00000101011" % (self.regs[d.group('b').lower()],
                                                        self.regs[d.group('c').lower()],
                                                        self.regs[d.group('a').lower()])
                return self.to_int(codigo_bin)
            else:
                self.controle.add_msg("Erro Montagem (%d): Os operandos da instrução 'sltu' devem ser todos registradores" % linha)
                return None
        else:
            self.controle.add_msg("Erro Montagem (%d): A instrução 'sltu' deve ter 3 operandos" % linha)
            return None
        
    def cod_sra(self, resto, linha):
        d = re.search('(?P<a>\$\d{1,2}) *?, *?(?P<b>\$\d{1,2}) *?, *?((?P<c>(\d{1,5}))|(?P<r>[a-zA-Z][\w_]*?))$', resto)
        if d:
            
            if(d.group('c')):
                imm = int(d.group('c'))
            elif (d.group('r')):
                try:
                    imm = int(self.tabela_simbolo[d.group('r')])
                except KeyError:
                    self.controle.add_msg("Erro Montagem (%d): Símbolo %s indefinido!" % (linha, d.group('r')))
                    return None
                
            if d.group('a').lower() in self.regs and \
                    d.group('b').lower() in self.regs:
                codigo_bin = "00000000000%s%s%s000011" % (self.regs[d.group('b').lower()],
                                                        self.regs[d.group('a').lower()],
                                                        self.to_bin(imm, 5)
                                                        )
                return self.to_int(codigo_bin)
            else:
                self.controle.add_msg("Erro Montagem (%d): Os operandos da instrução 'sra' são dois registradores seguidos por um deslocamento de 5-bits (0-31)" % linha)
                return None
        else:
            self.controle.add_msg("Erro Montagem (%d): Formato da instrução 'sra': $d, $s, imd onde imd é um imediato ou rótulo" % linha)
            return None  
    
    def cod_srl(self, resto, linha):
        d = re.search('(?P<a>\$\d{1,2}) *?, *?(?P<b>\$\d{1,2}) *?, *?((?P<c>(\d{1,5}))|(?P<r>[a-zA-Z][\w_]*?))$', resto)
        if d:
            
            if(d.group('c')):
                imm = int(d.group('c'))
            elif (d.group('r')):
                try:
                    imm = int(self.tabela_simbolo[d.group('r')])
                except KeyError:
                    self.controle.add_msg("Erro Montagem (%d): Símbolo %s indefinido!" % (linha, d.group('r')))
                    return None
                
            if d.group('a').lower() in self.regs and \
                    d.group('b').lower() in self.regs:
                codigo_bin = "00000000000%s%s%s000010" % (self.regs[d.group('b').lower()],
                                                        self.regs[d.group('a').lower()],
                                                        self.to_bin(imm, 5)
                                                        )
                return self.to_int(codigo_bin)
            else:
                self.controle.add_msg("Erro Montagem (%d): Os operandos da instrução 'srl' são dois registradores seguidos por um deslocamento de 5-bits (0-31)" % linha)
                return None
        else:
            self.controle.add_msg("Erro Montagem (%d): Formato da instrução 'srl': $d, $s, imd onde imd é um imediato ou rótulo" % linha)
            return None  
    
    def cod_srlv(self, resto, linha):
        d = re.search('(?P<a>\$\d{1,2}) *?, *?(?P<b>\$\d{1,2}) *?, *?(?P<c>\$\d{1,2})', resto)
        if d:
            if d.group('a').lower() in self.regs and \
                    d.group('b').lower() in self.regs and \
                    d.group('c').lower() in self.regs:
                codigo_bin = "000000%s%s%s00000000110" % (self.regs[d.group('c').lower()],
                                                        self.regs[d.group('b').lower()],
                                                        self.regs[d.group('a').lower()])
                return self.to_int(codigo_bin)
            else:
                self.controle.add_msg("Erro Montagem (%d): Os operandos da instrução 'srlv' devem ser todos registradores" % linha)
                return None
        else:
            self.controle.add_msg("Erro Montagem (%d): A instrução 'srlv' deve ter 3 operandos" % linha)
            return None         
    
    def cod_sub(self, resto, linha):
        d = re.search('(?P<a>\$\d{1,2}) *?, *?(?P<b>\$\d{1,2}) *?, *?(?P<c>\$\d{1,2})', resto)
        if d:
            if d.group('a').lower() in self.regs and \
                    d.group('b').lower() in self.regs and \
                    d.group('c').lower() in self.regs:
                codigo_bin = "000000%s%s%s00000100010" % (self.regs[d.group('b').lower()],
                                                        self.regs[d.group('c').lower()],
                                                        self.regs[d.group('a').lower()])
                return self.to_int(codigo_bin)
            else:
                self.controle.add_msg("Erro Montagem (%d): Os operandos da instrução 'sub' devem ser todos registradores" % linha)
                return None
        else:
            self.controle.add_msg("Erro Montagem (%d): A instrução 'sub' deve ter 3 operandos" % linha)
            return None
    
    def cod_subu(self, resto, linha):
        d = re.search('(?P<a>\$\d{1,2}) *?, *?(?P<b>\$\d{1,2}) *?, *?(?P<c>\$\d{1,2})', resto)
        if d:
            if d.group('a').lower() in self.regs and \
                    d.group('b').lower() in self.regs and \
                    d.group('c').lower() in self.regs:
                codigo_bin = "000000%s%s%s00000100011" % (self.regs[d.group('b').lower()],
                                                        self.regs[d.group('c').lower()],
                                                        self.regs[d.group('a').lower()])
                return self.to_int(codigo_bin)
            else:
                self.controle.add_msg("Erro Montagem (%d): Os operandos da instrução 'subu' devem ser todos registradores" % linha)
                return None
        else:
            self.controle.add_msg("Erro Montagem (%d): A instrução 'subu' deve ter 3 operandos" % linha)
            return None
    
    def cod_sw(self, resto, linha):
        d = re.search("(?P<a>\$\d{1,2}) *?, *?((?P<o>(\d{1,5}))|(?P<r>[a-zA-Z][\w_]*?)) *?\( *?(?P<c>\$\d{1,2}) *?\) *?", resto)
        if d:
            
            if(d.group('o')):
                imm = int(d.group('o'))
            elif (d.group('r')):
                try:
                    imm = int(self.tabela_simbolo[d.group('r')])
                except KeyError:
                    self.controle.add_msg("Erro Montagem (%d): Símbolo %s indefinido!" % (linha, d.group('r')))
                    return None                  
            
            if d.group('a').lower() in self.regs and \
                    d.group('c').lower() in self.regs:
                codigo_bin = "101011%s%s%s" % (self.regs[d.group('c').lower()],
                                                    self.regs[d.group('a')],
                                                    self.to_bin(imm, 16)
                                              )
                return self.to_int(codigo_bin)
            else:
                self.controle.add_msg("Erro Montagem (%d): O operando da instrução 'sw' deve estar no formato sw $r1, offset($r2)" % linha)
                return None
        else:
            self.controle.add_msg("Erro Montagem (%d): Formato da instrução 'sw': sw $r1, offset($r2) onde offset pode ser um imediato ou um símbolo")
            return None
    
    def cod_syscall(self, resto, linha):
        codigo_bin = "00000000000000000000000000001100"
        return self.to_int(codigo_bin)
    
    def cod_xor(self, resto, linha):
        d = re.search('(?P<a>\$\d{1,2}) *?, *?(?P<b>\$\d{1,2}) *?, *?(?P<c>\$\d{1,2})', resto)
        if d:
            if d.group('a').lower() in self.regs and \
                    d.group('b').lower() in self.regs and \
                    d.group('c').lower() in self.regs:
                codigo_bin = "000000%s%s%s00000100110" % (self.regs[d.group('b').lower()],
                                                        self.regs[d.group('c').lower()],
                                                        self.regs[d.group('a').lower()])
                return self.to_int(codigo_bin)
            else:
                self.controle.add_msg("Erro Montagem (%d): Os operandos da instrução 'xor' devem ser todos registradores" % linha)
                return None
        else:
            self.controle.add_msg("Erro Montagem (%d): A instrução 'xor' deve ter 3 operandos" % linha)
            return None        
    
    def cod_xori(self, resto, linha):
        d = re.search('(?P<a>\$\d{1,2}) *?, *?(?P<b>\$\d{1,2}) *?, *?((?P<c>(\d{1,5}))|(?P<r>[a-zA-Z][\w_]*?))$', resto)
        if d:
            
            if(d.group('c')):
                imm = int(d.group('c'))
            elif (d.group('r')):
                try:
                    imm = int(self.tabela_simbolo[d.group('r')])
                except KeyError:
                    self.controle.add_msg("Erro Montagem (%d): Símbolo %s indefinido!" % (linha, d.group('r')))
                    return None
                
            if d.group('a').lower() in self.regs and \
                    d.group('b').lower() in self.regs:
                codigo_bin = "001110%s%s%s" % (self.regs[d.group('b').lower()],
                                                        self.regs[d.group('a').lower()],
                                                        self.to_bin(imm, 16)
                                                        )
                return self.to_int(codigo_bin)
            else:
                self.controle.add_msg("Erro Montagem (%d): Os operandos da instrução 'xori' são dois registradores seguidos por um valor imediato de 16-bits" % linha)
                return None
        else:
            self.controle.add_msg("Erro Montagem (%d): Formato da instrução 'xori': $d, $s, imd onde imd é um imediato ou rótulo" % linha)
            return None
    